package com.project.imageinterference.utils;

import org.springframework.util.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoUnit;
import java.util.*;

/**
 * @Description 时间工具类
 * @author haochuanwan
 * @date 2022/5/27 15:25
 **/
public class DateTimeUtils {

    public static final String STANDARD_DATE="yyyy-MM-dd";
    public static final String STANDARD_DATE_TIME="yyyy-MM-dd HH:mm:ss";

    public static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern(STANDARD_DATE);
    public static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern(STANDARD_DATE_TIME);

    /**
     * 获取当前日期（标准字符串格式）
     */
    public static final String getNowDateStr(){
        return LocalDate.now().format(DATE_FORMATTER);
    }

    /**
     * 获取当前日期时间（标准字符串格式）
     */
    public static final String getNowDateTimeStr(){
        return LocalDateTime.now().format(DATE_TIME_FORMATTER);
    }

    /**
     * 当前时间增加1秒
     * @return
     */
    public static final String getNowDateTimeStrPlusSeconds(String nowDateTimeStr){
        DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern(STANDARD_DATE_TIME);
        LocalDateTime nowDate = LocalDateTime.parse(nowDateTimeStr, inputFormatter);
        LocalDateTime localDateTimePlusSeconds = nowDate.plusSeconds(1L);
        return localDateTimePlusSeconds.format(DATE_TIME_FORMATTER);
    }
    public static boolean isValidDate(String str) {
        boolean convertSuccess=true;
        // 指定日期格式为四位年/两位月份/两位日期，注意yyyy/MM/dd区分大小写；
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            //设置lenient为false. 否则SimpleDateFormat会比较宽松地验证日期，比如2007/02/29会被接受，并转换成2007/03/01
            format.setLenient(false);
            format.parse(str);
        } catch (ParseException e) {
            // e.printStackTrace();
            // 如果throw java.text.ParseException或者NullPointerException，就说明格式不对
            convertSuccess=false;
        }
        return convertSuccess;
    }

    public static Date stringToDate(String str,SimpleDateFormat simpleDateFormat) throws ParseException {
        if(isValidDate(str)){
            return simpleDateFormat.parse(str);
        }else {
            return null;
        }
    }


    /**
     * 获取两个日期相差的天数  方法一
     *
     * @param startDate 开始日期的字符串  yyyy-MM-dd
     * @param endDate   结束日期的字符串  yyyy-MM-dd
     * @return 相差天数，如果解析失败则返回-1
     **/
    public static long subDaysByDate(String startDate, String endDate) {
        long sub;
        try {
            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(STANDARD_DATE);
            LocalDate start = LocalDate.parse(startDate, dateTimeFormatter);
            LocalDate end = LocalDate.parse(endDate, dateTimeFormatter);
            sub = Duration.between(LocalDateTime.of(start, LocalTime.of(0,0,0)),
                    LocalDateTime.of(end, LocalTime.of(0,0,0))).toDays();
        } catch (DateTimeParseException e) {
            sub = -1;
        }
        return sub;
    }


    /**
     * 获取两个日期相差的天数  方法二
     *
     * @param startDate 开始日期的字符串
     * @param endDate   结束日期的字符串
     * @return 相差天数，如果解析失败则返回-1
     **/
    public static long subDaysByDate2(String startDate, String endDate) {
        long sub;
        try {
            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(STANDARD_DATE);
            LocalDate start = LocalDate.parse(startDate, dateTimeFormatter);
            LocalDate end = LocalDate.parse(endDate, dateTimeFormatter);

            sub = end.toEpochDay() - start.toEpochDay();
        } catch (DateTimeParseException e) {
            sub = -1;
        }
        return sub;
    }


    /**
     * 获取两个日期相差的天数,丢球最后的时间
     * @param startDate 开始日期的字符串
     * @param endDate   结束日期的字符串
     * @return 相差天数，如果解析失败则返回-1
     **/
    public static long subDaysByDateTime(String startDate, String endDate) {
        long sub;
        try {
            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(STANDARD_DATE_TIME);
            LocalDateTime start = LocalDateTime.parse(startDate, dateTimeFormatter);
            LocalDateTime end = LocalDateTime.parse(endDate, dateTimeFormatter);
            sub = Duration.between(start, end).toDays();
        } catch (DateTimeParseException e) {
            sub = -1;
        }
        return sub;
    }

    /**
     * 获取两个时间字符串差值
     * @param startTime
     * @param endTime
     * @return
     */
    public static Map<String,Long> timeDiff(String startTime, String endTime){
        Map map = new HashMap<String,Long>(7);
        //将String转LocalDateTime
        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime startLocalTime = LocalDateTime.parse(startTime,fmt);
        LocalDateTime endLocalTime = LocalDateTime.parse(endTime,fmt);
        //判断相差几年，相差几月，相差几天
        long yearDiff = ChronoUnit.YEARS.between(startLocalTime, endLocalTime);
        map.put("yearDiff",yearDiff);

        long monthDiff = ChronoUnit.MONTHS.between(startLocalTime, endLocalTime);
        map.put("monthDiff",monthDiff);

        long dayDiff = ChronoUnit.DAYS.between(startLocalTime, endLocalTime);
        map.put("dayDiff",dayDiff);

        //相差几小时，相差几分钟，相差几秒
        long hourDiff = ChronoUnit.HOURS.between(startLocalTime, endLocalTime);
        map.put("hourDiff",hourDiff);

        long minuteDiff = ChronoUnit.MINUTES.between(startLocalTime, endLocalTime);
        map.put("minuteDiff",minuteDiff);

        long secondDiff = ChronoUnit.SECONDS.between(startLocalTime, endLocalTime);
        map.put("secondDiff",secondDiff);

        //相差多少个半天
        long halfDayDiff = ChronoUnit.HALF_DAYS.between(startLocalTime, endLocalTime);
        map.put("halfDayDiff",halfDayDiff);
        return map;
    }

    /**
     * 获取时间字符串与当前时间差值
     * @param timeStr
     * @return
     */
    public static Map<String,Long> nowTimeDiff(String timeStr){
        Map map = new HashMap<String,Long>(7);
        //获取当前时间
        LocalDateTime today = LocalDateTime.now();
        //将String转LocalDateTime
        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime localTimeStr = LocalDateTime.parse(timeStr,fmt);
        //判断相差几年，相差几月，相差几天
        long yearDiff = ChronoUnit.YEARS.between(localTimeStr, today);
        map.put("yearDiff",yearDiff);

        long monthDiff = ChronoUnit.MONTHS.between(localTimeStr, today);
        map.put("monthDiff",monthDiff);

        long dayDiff = ChronoUnit.DAYS.between(localTimeStr, today);
        map.put("dayDiff",dayDiff);

        //相差几小时，相差几分钟，相差几秒
        long hourDiff = ChronoUnit.HOURS.between(localTimeStr, today);
        map.put("hourDiff",hourDiff);

        long minuteDiff = ChronoUnit.MINUTES.between(localTimeStr, today);
        map.put("minuteDiff",minuteDiff);

        long secondDiff = ChronoUnit.SECONDS.between(localTimeStr, today);
        map.put("secondDiff",secondDiff);

        //相差多少个半天
        long halfDayDiff = ChronoUnit.HALF_DAYS.between(localTimeStr, today);
        map.put("halfDayDiff",halfDayDiff);
        return map;
    }

    /**
     * 获取前一天近一周的工作日集合
     * @return
     */
    public static List<String> getWorkDays(){
        List<String> workDays = new ArrayList<>();
        LocalDate currentDate = LocalDate.now().minusDays(1);
        LocalDate startDate = LocalDate.now().minusDays(7);

        // 从开始日期到当前日期之间的所有日期
        LocalDate date = startDate;
        while (date.isBefore(currentDate) || date.isEqual(currentDate)) {
            if (date.getDayOfWeek() != DayOfWeek.SATURDAY && date.getDayOfWeek() != DayOfWeek.SUNDAY) {
                workDays.add(date.format(DATE_FORMATTER));
            }
            date = date.plusDays(1);
        }
        return workDays;
    }

    /**
     * 获取前一天往前推一周的日期list
     * @return
     */
    public static List<String> getNowMinusDays (){
        List<String> list = new ArrayList<>();
        for (int i = 1; i < 8; i++) {
            String dayStr = LocalDate.now().minusDays(i).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            list.add(dayStr);
        }
        return list;
    }

    /**
     * 获取指定日期前一天近一周的日期list
     * @param dateStr
     * @return
     */
    public static List<String> getMinusDaysForDateStr(String dateStr){
        LocalDate startDate = null;
        if(StringUtils.isEmpty(dateStr)){
            startDate = LocalDate.now();
        }else{
            startDate = LocalDate.parse(dateStr,DATE_FORMATTER);
        }
        List<String> list = new ArrayList<>();
        for (int i = 1; i < 8; i++) {
            String dayStr = startDate.minusDays(i).format(DATE_FORMATTER);
            list.add(dayStr);
        }
        return list;
    }

    /**
     * 获取指定日期前一天近一周的工作日集合
     * @param dateStr
     * @return
     */
    public static List<String> getWorkDaysForDateStr(String dateStr){
        List<String> workDays = new ArrayList<>();
        LocalDate currentDate = null;
        LocalDate startDate = null;
        if(StringUtils.isEmpty(dateStr)){
            currentDate = LocalDate.now().minusDays(1);
            startDate = LocalDate.now().minusDays(7);
        }else{
            currentDate = LocalDate.parse(dateStr,DATE_FORMATTER).minusDays(1);
            startDate = LocalDate.parse(dateStr,DATE_FORMATTER).minusDays(7);
        }
        // 从开始日期到当前日期之间的所有日期
        LocalDate date = startDate;
        while (date.isBefore(currentDate) || date.isEqual(currentDate)) {
            if (date.getDayOfWeek() != DayOfWeek.SATURDAY && date.getDayOfWeek() != DayOfWeek.SUNDAY) {
                workDays.add(date.format(DATE_FORMATTER));
            }
            date = date.plusDays(1);
        }
        return workDays;
    }

    /**
     * 获取最近2小时的日期时间字符串
     * @return
     */
    public static Map<String,String> getDateMap2() {
        Map<String,String> map = new HashMap<>();
        LocalDateTime localDateTime = LocalDateTime.now();
        LocalDate localDate = localDateTime.toLocalDate();
        String endDate = localDate.format(DATE_FORMATTER);
        //获取小时
        LocalTime localTime = LocalTime.now();
        int hour = localTime.getHour();
        String endDateTime = endDate.concat(" ").concat(String.valueOf(hour)).concat(":00:00");

        String beginDate = "";
        String beginDateTime = "";
        if(hour == 0){
            LocalDate localDate1 = localDate.minusDays(1);
            beginDate = localDate1.format(DATE_FORMATTER);
            beginDateTime = beginDate.concat(" ").concat(String.valueOf(23)).concat(":00:00");
        }else{
            LocalTime minusHours = localTime.minusHours(2);
            int minusHour = minusHours.getHour();
            beginDateTime = endDate.concat(" ").concat(String.valueOf(minusHour)).concat(":00:00");
        }
        map.put("beginDateTime",beginDateTime);
        map.put("endDateTime",endDateTime);
        return map;
    }

    /**
     * 获取最近2小时的日期时间字符串
     * @return
     */
    public static Map<String,String> getDateMap() {
        Map<String,String> map = new HashMap<>();
        LocalDateTime localDateTime = LocalDateTime.now();
        LocalDate localDate = localDateTime.toLocalDate();
        String endDate = localDate.format(DATE_FORMATTER);
        //获取小时
        LocalTime localTime = LocalTime.now();
        int hour = localTime.getHour();
        switch (hour){
            case 9:
                hour = 8;
                break;
            case 11:
                hour = 10;
                break;
            case 13:
                hour = 12;
                break;
            case 15:
                hour = 14;
                break;
            case 17:
                hour = 16;
                break;
            case 19:
                hour = 18;
                break;
        }
        String endDateTime = endDate.concat(" ").concat(String.valueOf(hour)).concat(":00:00");
        String beginDate = "";
        String beginDateTime = "";
        if(hour == 0){
            LocalDate localDate1 = localDate.minusDays(1);
            beginDate = localDate1.format(DATE_FORMATTER);
            beginDateTime = beginDate.concat(" ").concat(String.valueOf(23)).concat(":00:00");
        }else{
            int minusHour = hour - 2;
            beginDateTime = endDate.concat(" ").concat(String.valueOf(minusHour)).concat(":00:00");
        }
        map.put("beginDateTime",beginDateTime);
        map.put("endDateTime",endDateTime);
        return map;
    }


    /**
     * 判断传入的时间是否为工作日、工作时间
     * @param dateStr
     * @return
     */
    public static boolean checkWeekDayAndWeekHour(String dateStr){
        List<Integer> weekDays = new ArrayList<>();
        weekDays.add(1);
        weekDays.add(2);
        weekDays.add(3);
        weekDays.add(4);
        weekDays.add(5);

        List<Integer> weekHours = new ArrayList<>();
        weekHours.add(8);
        weekHours.add(10);
        weekHours.add(12);
        weekHours.add(14);
        weekHours.add(16);
        weekHours.add(18);

        LocalDateTime localDate=LocalDateTime.parse(dateStr, DATE_TIME_FORMATTER);
        int dayOfWeek = localDate.getDayOfWeek().getValue();
        int hour = localDate.getHour();

        if(!weekDays.contains(dayOfWeek)){
            return false;
        }else if(!weekHours.contains(hour)){
            return false;
        }
        return true;
    }

    /**
     * 获取当前日期：格式为 x月x日，例：8月22日
     * @return
     */
    public static String getNowDate(){
        // 获取当前日期
        LocalDate currentDate = LocalDate.now();

        // 定义日期格式化器，指定输出格式为"MM-dd"
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM-dd");

        // 格式化日期
        String formattedDate = currentDate.format(formatter);

        // 将格式化后的日期转换为 "x月x日" 形式
        String convertedDate = convertToChineseDate(formattedDate);
//        System.out.println("当前日期（转换前）: " + formattedDate);
//        System.out.println("当前日期（转换后）: " + convertedDate);
        return convertedDate;
    }

    // 将格式化后的日期转换为 "x月x日" 形式
    public static String convertToChineseDate(String formattedDate) {
        String[] parts = formattedDate.split("-");
        int month = Integer.parseInt(parts[0]);
        int day = Integer.parseInt(parts[1]);
        return month + "月" + day + "日";
    }

    // 将格式化后的日期转换为 "x月x日" 形式
    public static String formatTime(Date time) {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String timeStr=null;
        try {
            timeStr = df.format(time);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return timeStr;
    }

    /**
     * 根据时间类型返回开始时间和结束时间
     * @param timeType 今天、近7天、近30天、近90天、近半年、近一年
     * @return
     */
    public static Map<String,String> convertPublishTime(String timeType){
        Map<String,String> map = new HashMap<>();
        if(StringUtils.isEmpty(timeType)){
            return map;
        }
        // 获取当前时间
        LocalDateTime currentDateTime = LocalDateTime.now();
        // 定义日期时间格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
        LocalDateTime startTime = null;
        LocalDateTime preTimeAgo = null;
        // 当天最大时间（23:59:59）
        LocalDateTime endTime = currentDateTime.withHour(23).withMinute(59).withSecond(59).withNano(0);
        if("今天".equals(timeType)){
            // 获取当天最小时间（凌晨00:00:00）
            startTime = currentDateTime.withHour(0).withMinute(0).withSecond(0).withNano(0);
            // 格式化最小时间和最大时间字符串
            map.put("startTime", startTime.format(formatter));
            map.put("endTime", endTime.format(formatter));
        }else if("近7天".equals(timeType)){
            preTimeAgo = currentDateTime.minusDays(7);
            startTime = preTimeAgo.withHour(0).withMinute(0).withSecond(0).withNano(0);
            // 格式化最小时间和最大时间字符串
            map.put("startTime", startTime.format(formatter));
            map.put("endTime", endTime.format(formatter));
        }else if("近30天".equals(timeType)){
            preTimeAgo = currentDateTime.minusDays(30);
            startTime = preTimeAgo.withHour(0).withMinute(0).withSecond(0).withNano(0);
            // 格式化最小时间和最大时间字符串
            map.put("startTime", startTime.format(formatter));
            map.put("endTime", endTime.format(formatter));
        }else if("近90天".equals(timeType)){
            preTimeAgo = currentDateTime.minusDays(90);
            startTime = preTimeAgo.withHour(0).withMinute(0).withSecond(0).withNano(0);
            // 格式化最小时间和最大时间字符串
            map.put("startTime", startTime.format(formatter));
            map.put("endTime", endTime.format(formatter));
        }else if("近半年".equals(timeType)){
            preTimeAgo = currentDateTime.minusMonths(6);
            startTime = preTimeAgo.withHour(0).withMinute(0).withSecond(0).withNano(0);
            // 格式化最小时间和最大时间字符串
            map.put("startTime", startTime.format(formatter));
            map.put("endTime", endTime.format(formatter));
        }else if("近一年".equals(timeType)){
            preTimeAgo = currentDateTime.minusYears(1);
            startTime = preTimeAgo.withHour(0).withMinute(0).withSecond(0).withNano(0);
            // 格式化最小时间和最大时间字符串
            map.put("startTime", startTime.format(formatter));
            map.put("endTime", endTime.format(formatter));
        }
        return map;
    }

    /**
     * 时间字符串转换成时间戳
     * @param dateString
     * @return
     */
    public static String convertToTimestamp(String dateString) {
        if(StringUtils.isEmpty(dateString)){
            return "";
        }
        try {
            // 解析日期字符串
            LocalDate date = LocalDate.parse(dateString);
            // 转换为时间戳（秒）
            long timestamp = date.atStartOfDay().toEpochSecond(ZoneOffset.UTC);
            // 转换为字符串
            return String.valueOf(timestamp);
        }catch (Exception e){
            e.printStackTrace();
            return "";
        }
    }

    public static void main(String[] args) {
        Date date=new Date();
        System.out.println(formatTime(date));
//        List<String> nowMinusDays = getNowMinusDays();
//        System.out.println(nowMinusDays);
//
//        List<String> weekDays = getWorkDays();
//        System.out.println(weekDays);

        List<String> minusDays = getMinusDaysForDateStr("2023-06-09");
        System.out.println("指定日期：" + minusDays);
        List<String> minusDays1 = getMinusDaysForDateStr("");
        System.out.println("不指定：" + minusDays1);

        List<String> workDaysForDateStr = getWorkDaysForDateStr("2023-06-09");
        System.out.println("指定日期：" + workDaysForDateStr);
        List<String> workDaysForDateStr1 = getWorkDaysForDateStr("");
        System.out.println("不指定：" + workDaysForDateStr1);

        Map<String, String> dateMap = getDateMap();
        System.out.println(dateMap);
    }
    
}
